﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using RSSReader.DAL;
using RSSReader.Repository;
using System.Data.Entity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace RSSReader.WCFWebRole
{
  public class DataDistributor : IDataDistributor
  {
    private IRssRepository _repository { get; set; }

    public DataDistributor()
    {
      this._repository = new RssRepository();
    }

    public string GetUserId(string userName)
    {
      var User = this._repository.GetUserByUserName(userName);
      return User != null ? User.Id : "";
    }

    public UserInformation GetUser(string userName, string passwordHash)
    {
      return new UserInformation(this._repository.GetUser(userName, passwordHash));
    }

    public IEnumerable<UserInformation> GetUsers()
    {
      return this._repository.GetUsers().Select(s => new UserInformation(s));
    }

    public UserInformation CreateUser(string userName, string passwordHash, string email)
    {
      var User = this._repository.GetUserByUserName(userName);
      if (User != null)
        return new UserInformation();
      //this._repository.GetUserId
      ApplicationUser NewUser = new ApplicationUser
                                {
                                  UserName = userName,
                                  PasswordHash = passwordHash,
                                  Email = email,
                                  EmailConfirmed = true,
                                };

      string NewId;

      do
      {
        NewId = Guid.NewGuid().ToString();
      } while (this._repository.GetUser(NewId) != null);

      NewUser.Id = NewId;

      this._repository.AddUser(NewUser);

      this._repository.SaveChanges();

      return new UserInformation(NewUser);
    }

    public IEnumerable<UserSubscriptionInformation> GetSubscriptions(string userId)
    {
      var Subs = this._repository.GetUserSubscriptions(userId);
      return Subs.Select(s => new UserSubscriptionInformation(s));
    }

    public void RemoveSubscriptions(IEnumerable<string> subs, string userId)
    {
      var Sources = this._repository.GetSources(subs);
      var Subscriptions = this._repository.GetSubscriptions(userId, Sources.Select(s => s.Id));

      foreach (var sub in Subscriptions)
        sub.IsSubscribe = false;

      this._repository.SaveChanges();
    }

    public void SetSubscriptions(IEnumerable<UserSubscriptionInformation> subs, string userId)
    {
      var Sources = this._repository.GetSources(subs.Select(s => s.Url)).ToList();
      var ExistingSourceUrls = Sources.Select(s => s.Url);
      var SourcesToAdd = subs.Where(w => !ExistingSourceUrls.Contains(w.Url));

      foreach (var sub in SourcesToAdd)
      {
        var GoodUrl = sub.Url.Length > 2083 ? sub.Url.Substring(0, 2083) : sub.Url;
        var GoodTitle = sub.Title.Length > 200 ? sub.Title.Substring(0, 200) : sub.Title;
        var GoodDesc = sub.Description.Length > 2048 ? sub.Description.Substring(0, 2048) : sub.Description;

        var Source = new Source { Url = GoodUrl, Description = GoodTitle, Title = GoodDesc };
        this._repository.AddSource(Source);
        Sources.Add(Source);
      }

      var ExistingSubscriptions = this._repository.GetSubscriptions(userId, Sources.Select(s => s.Id));

      foreach (var sub in ExistingSubscriptions)
        sub.IsSubscribe = true;

      var ExistringSubscriptionIds = ExistingSubscriptions.Select(s => s.SourceId);

      var SubscriptionToCreate = Sources.Where(w => !ExistringSubscriptionIds.Contains(w.Id));

      foreach (var source in SubscriptionToCreate)
      {
        var Sub = new Subscription { IsSubscribe = true, UserId = userId };
        Sub.Source = source;
        this._repository.AddSubscription(Sub);
      }

      this._repository.SaveChanges();
    }

    public void UpdateUserArticles(Dictionary<UserSubscriptionInformation, IEnumerable<UserArticleInformation>> feeds, string userId)
    {
      var SourceUrls = feeds.Select(s => s.Key);

      var Sources = this._repository.GetSources(SourceUrls.Select(s => s.Url)).ToList();
      var ExistingsSourcesUrl = Sources.Select(s => s.Url);
      var SourcesUrlToCreate = SourceUrls.Where(w => !ExistingsSourcesUrl.Contains(w.Url));

      foreach (var src in SourcesUrlToCreate)
      {
        var GoodUrl = src.Url.Length > 2083 ? src.Url.Substring(0, 2083) : src.Url;
        var GoodTitle = src.Title.Length > 200 ? src.Title.Substring(0, 200) : src.Title;
        var GoodDesc = src.Description.Length > 2048 ? src.Description.Substring(0, 2048) : src.Description;

        var Src = new Source { Url = GoodUrl, Title = GoodTitle, Description = GoodDesc };
        this._repository.AddSource(Src);
        Sources.Add(Src);
      }

      foreach (var updates in feeds)
      {
        var Source = Sources.Where(w => w.Url == updates.Key.Url).FirstOrDefault();
        var ArticlesUrl = updates.Value.Select(s => s.Url);
        var Articles = this._repository.GetArticles(ArticlesUrl).ToList();
        var ExistingArticleUrls = Articles.Select(s => s.Url);

        var ArticlesToCreate = updates.Value.Where(w => !ExistingArticleUrls.Contains(w.Url));

        foreach (var toCreate in ArticlesToCreate)
        {
          var GoodUrl = toCreate.Url.Length > 2083 ? toCreate.Url.Substring(0, 2083) : toCreate.Url;
          var GoodTitle = toCreate.Title.Length > 200 ? toCreate.Title.Substring(0, 200) : toCreate.Title;
          var GoodDesc = toCreate.Description.Length > 2048 ? toCreate.Description.Substring(0, 2048) : toCreate.Description;

          var NewArticle = new Article { Url = GoodUrl, Source = Source, Title = GoodTitle, Description = GoodDesc, PublicationDate = toCreate.PublicationDate };
          this._repository.AddArticle(NewArticle);
          Articles.Add(NewArticle);
        }

        var ExistingUserArticles = this._repository.GetUserArticles(userId, Articles.Select(s => s.Id));

        foreach (var info in ExistingUserArticles)
        {
          var CurrentArticles = Articles.Where(w => w.Id == info.ArticleId).FirstOrDefault();
          var NewInfo = updates.Value.Where(w => w.Url == CurrentArticles.Url).FirstOrDefault();
          info.IsFavorite = NewInfo.IsFavorite;
        }

        var UserArticleToCreate = Articles.Where(w => !ExistingUserArticles.Select(s => s.ArticleId).Contains(w.Id));
        foreach (var toCreate in UserArticleToCreate)
        {
          var Info = updates.Value.Where(w => w.Url == toCreate.Url).FirstOrDefault();
          var UserArticle = new UserArticle { IsFavorite= Info.IsFavorite, Article = toCreate, UserId = userId };
          this._repository.AddUserArticle(UserArticle);
        }
      }

      this._repository.SaveChanges();
    }

    public Dictionary<string, IEnumerable<UserArticleInformation>> GetUserArticles(IEnumerable<string> feedsUrl, string userId)
    {
      Dictionary<string, IEnumerable<UserArticleInformation>> Res = new Dictionary<string, IEnumerable<UserArticleInformation>>();

      var ArticlesInfo = this._repository.GetUserArticlesVW(userId, feedsUrl);
      var Sources = this._repository.GetSources(ArticlesInfo.Select(s => s.SourceId));

      foreach (var Src in Sources)
        Res[Src.Url] = ArticlesInfo.Where(w => w.SourceId == Src.Id).Select(s => new UserArticleInformation(s));

      return Res;
    }
    public Dictionary<UserSubscriptionInformation, IEnumerable<UserArticleInformation>> GetUserFavorites(string userId)
    {
      Dictionary<UserSubscriptionInformation, IEnumerable<UserArticleInformation>> Dico = new Dictionary<UserSubscriptionInformation, IEnumerable<UserArticleInformation>>();

      var Favs = this._repository.GetUserFavorites(userId);
      var SourcesId = Favs.Select(s => s.SourceId).Distinct();

      var Sources = this._repository.GetSources(SourcesId);

      foreach(var src in Sources)
      {
        var UserSubInfo = new UserSubscriptionInformation { Description = src.Description, Url = src.Url, Title = src.Title };
        Dico[UserSubInfo] = Favs.Where(w => w.SourceId == src.Id).Select(s => new UserArticleInformation(s));
      }

      return Dico;
    }
  }
}